package com.steak.zk.lock;

import com.steak.zk.domain.LockObj;
import lombok.AllArgsConstructor;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 刘牌
 * @Title:
 * @date 2022/3/1910:20
 */
@AllArgsConstructor
public class Lock implements LockI{

    private CuratorFramework curatorFramework;
    private final String ROOT = "/lock";
    //锁前缀
    private final String lockPrefix = "/seq-";
    //序号
    private AtomicInteger lockSerialNumber = new AtomicInteger(0);
    //当前节点
    private String currentLockNode = "";
    //前一个锁节点
    private String previousLockNode = "";

    public Lock() throws Exception {
        if (!isExistRoot()) curatorFramework.create().withMode(CreateMode.EPHEMERAL).forPath(ROOT,"lockRoot".getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public boolean lock(LockObj lockObj) throws Exception {
        //获取锁成功
        if (isFirst(nodeList(),lockPrefix + lockSerialNumber.get())) return true;
        //保存当前节点
        currentLockNode = lockPrefix + lockSerialNumber.get();
        //保存前一个节点
        previousLockNode = lockPrefix + (lockSerialNumber.get() - 1);
        while (true){
            curatorFramework.getData().usingWatcher(new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    System.out.println("event  "+event);
                }
            }).forPath(previousLockNode);
            if (isFirst(nodeList(),currentLockNode)) return true;
        }
    }

    @Override
    public boolean unlock(LockObj lockObj) {
        return true;
    }

    //判断根节点是否存在
    boolean isExistRoot() throws Exception {
        return  null != curatorFramework.checkExists().forPath(ROOT) ;
    }
    //获取所有节点
    List<String> nodeList() throws Exception {
       return curatorFramework.getChildren().forPath(ROOT);
    }
    //判断节点是否是第一个
    boolean isFirst(List<String> nodeList , String nodeName){
        return nodeList.get(0).equals(nodeName);
    }
}
